package com.stone.config;

import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.ServletUtil;
import com.alibaba.fastjson.JSON;
import com.stone.bean.AppResponse;
import com.stone.constant.Const;
import com.stone.entity.SysLog;
import com.stone.service.SysLogService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

/**
 * 日志切点类
 * 通知：advice(前置，后置，环绕)
 */
@Slf4j
@Aspect
@Component
public class SysLogAspectConfig {

    @Resource
    private SysLogService sysLogService;
    @Resource
    private RedisTemplate redisTemplate;

    /**
     * 切点：配置切点表达式
     * execution(* test.*.*(..))代表test包下所有类的所有方法都会被代理
     *
     * @annotation(com.stone.aop.SysLog) 指定注解
     */
    @Pointcut("execution(* com.stone.controller.api..*(..))")
    public void logAspect() {
    }

    /**
     * 环绕通知：自定义方法的执行时机。
     */
    @Around(value = "logAspect()")
    public Object aroundMethod(ProceedingJoinPoint joinPoint) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        SysLog logDO = new SysLog();
        // 登录人
        String token = request.getHeader(Const.AUTH);
        if (StrUtil.isNotBlank(token)) {
            logDO.setLoginUserId(SpringContextConfig.loginUserId(token));
            logDO.setLogName(SpringContextConfig.loginUserName(token));
        }
        logDO.setLogIp(ServletUtil.getClientIP(request));
        logDO.setLogController(joinPoint.getSignature().getDeclaringType().getSimpleName());
        logDO.setLogMethod(joinPoint.getSignature().getName());
        String body = ServletUtil.getBody(request);
        if (StrUtil.isNotBlank(body)) {
            logDO.setLogParam(body);
        } else {
            logDO.setLogParam(JSON.toJSONString(ServletUtil.getParamMap(request)));
        }
        long startTime = System.currentTimeMillis();
        Object result = null;
        try {
            // 执行业务
            result = joinPoint.proceed();
            logDO.setLogResult(JSON.toJSONString(result));
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            return AppResponse.failed();
        } finally {
            logDO.setLogConsume(System.currentTimeMillis() - startTime);
            // 记录日志
            sysLogService.save(logDO);
        }
        return result;
    }


}